package info.sean.util.loadbalance;



import info.sean.util.common.AtomicPositiveInteger;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by wenjing on 2017-4-12.
 */
public class RoundRobinLoadBalance {

    private final AtomicPositiveInteger sequence = new AtomicPositiveInteger();

    public <T extends Weighable> T select(List<T> entries) {

        int length = entries.size(); // 总个数
        int maxWeight = 0; // 最大权重
        int minWeight = Integer.MAX_VALUE; // 最小权重
        final LinkedHashMap<T, IntegerWrapper> invokerToWeightMap = new LinkedHashMap<>();
        int weightSum = 0;
        for (int i = 0; i < length; i++) {
            int weight = entries.get(i).getWeight();
            maxWeight = Math.max(maxWeight, weight); // 累计最大权重
            minWeight = Math.min(minWeight, weight); // 累计最小权重
            if (weight > 0) {
                invokerToWeightMap.put(entries.get(i), new IntegerWrapper(weight));
                weightSum += weight;
            }
        }

        int currentSequence = sequence.getAndIncrement();
        if (maxWeight > 0 && minWeight < maxWeight) { // 权重不一样
			if (weightSum == 0) {
				// 异常处理权重为0默认返回
				return entries.get(0);
			}
            int mod = currentSequence % weightSum;
            for (int i = 0; i < maxWeight; i++) {
                for (Map.Entry<T, IntegerWrapper> each : invokerToWeightMap.entrySet()) {
                    final T k = each.getKey();
                    final IntegerWrapper v = each.getValue();
                    if (mod == 0 && v.getValue() > 0) {
                        return k;
                    }
                    if (v.getValue() > 0) {
                        v.decrement();
                        mod--;
                    }
                }
            }
        }
        // 取模轮循
        return entries.get(currentSequence % length);
    }

    private static final class IntegerWrapper {
        public IntegerWrapper(int value) {
            this.value = value;
        }

        private int value;

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }

        public void decrement() {
            this.value--;
        }
    }

    public static void main(String[] args) {
		System.out.println("1581123726    1".replaceAll("\\s*", ""));
        List<String> zhongrongList = CapitalCodeEnum.ZHONGRONG_LIST;
        System.out.println("zhongrongList = " + zhongrongList);
        RoundRobinLoadBalance roundRobinLoadBalance = new RoundRobinLoadBalance();

    }
}
